package com.derbysoft.ota.application.service.impl;


import com.derbysoft.modules.eip.translator.Translator;
import com.derbysoft.modules.validation.ValidateUtils;
import com.derbysoft.ota.application.service.HotelAvailService;
import com.derbysoft.ota.application.translator.CodeTables;
import com.derbysoft.ota.application.translator.rs.HotelAvailRSSource;
import com.derbysoft.ota.interfaces.protocol._2009a.OTAHotelAvailRQ;
import com.derbysoft.ota.interfaces.protocol._2009a.OTAHotelAvailRS;
import com.derbysoft.ota.interfaces.protocol._2009a.POSType;
import com.derbysoft.ota.interfaces.protocol._2009a.WarningType;
import com.derbysoft.ota.interfaces.protocol._2009a.WarningsType;
import com.derbysoft.remote.dswitch.core.GenericRQ;
import com.derbysoft.remote.dswitch.core.GenericRS;
import com.derbysoft.remote.dswitch.core.RequestHeader;
import com.derbysoft.remote.dswitch.generic.constants.UniqueIDType;
import com.derbysoft.remote.dswitch.generic.dto.UniqueIDDTO;
import com.derbysoft.remote.dswitch.hotel.dswitch.DSwitch4HotelBuyerWebServiceFactory;
import com.derbysoft.remote.dswitch.hotel.dto.HotelMultiProviderAvailRQ;
import com.derbysoft.remote.dswitch.hotel.dto.HotelMultiProviderAvailRS;
import com.google.common.collect.Lists;
import com.google.inject.Inject;

public class HotelAvailServiceImpl extends AbstractService implements HotelAvailService {

	private Translator<OTAHotelAvailRQ, HotelMultiProviderAvailRQ> hotelAvailRQTranslator;
	private Translator<HotelAvailRSSource, OTAHotelAvailRS> hotelAvailRSTranslator;

	@Inject
	public HotelAvailServiceImpl(
		DSwitch4HotelBuyerWebServiceFactory dswitch4HotelBuyerWebServiceFactory,
		Translator<POSType, RequestHeader> requestHeaderTranslator,
		Translator<HotelAvailRSSource, OTAHotelAvailRS> hotelAvailRSTranslator,
		Translator<OTAHotelAvailRQ, HotelMultiProviderAvailRQ> hotelAvailRQTranslator) {
		
		super(dswitch4HotelBuyerWebServiceFactory, requestHeaderTranslator);
		this.hotelAvailRSTranslator = hotelAvailRSTranslator;
		this.hotelAvailRQTranslator = hotelAvailRQTranslator;
	}

	@Override
	public OTAHotelAvailRS get(OTAHotelAvailRQ otaHotelAvailRQ) {
		GenericRQ<HotelMultiProviderAvailRQ> genericRQ = switchRequest(otaHotelAvailRQ);

		ValidateUtils.validate(genericRQ);
		GenericRS<HotelMultiProviderAvailRS> genericRS = dswitch().getMultiProviderAvailability(genericRQ);
		ValidateUtils.validate(genericRS);

		return otaResponse(otaHotelAvailRQ, genericRS);
	}

	private GenericRQ<HotelMultiProviderAvailRQ> switchRequest(OTAHotelAvailRQ requestObject) {
		HotelMultiProviderAvailRQ payload = hotelAvailRQTranslator.translate(requestObject);
		RequestHeader header = requestHeader(requestObject.getPOS());
		header.setProducts(Lists.newArrayList(new UniqueIDDTO(hotelCode(requestObject), UniqueIDType.HOTEL)));
		GenericRQ<HotelMultiProviderAvailRQ> genericRQ = new GenericRQ<HotelMultiProviderAvailRQ>(
			header,
			payload
		);
		return genericRQ;
	}

	private String hotelCode(OTAHotelAvailRQ requestObject) {
		return requestObject.getAvailRequestSegments().getAvailRequestSegment().iterator().next()
				.getHotelSearchCriteria().getCriterion().iterator().next()
				.getHotelRef().iterator().next()
				.getHotelCode();
	}

	private OTAHotelAvailRS otaResponse(OTAHotelAvailRQ otaHotelAvailRQ, GenericRS<HotelMultiProviderAvailRS> switchRS) {
		OTAHotelAvailRS otaHotelAvailRS = new OTAHotelAvailRS();
		if (!handleResponseHeaders(switchRS, otaHotelAvailRQ, otaHotelAvailRS)) {
			otaHotelAvailRS =  hotelAvailRSTranslator.translate(
					new HotelAvailRSSource(switchRS.getPayload(), otaHotelAvailRQ, otaHotelAvailRS)
			);
		}
		
		if (otaHotelAvailRS.getRoomStays() == null || otaHotelAvailRS.getRoomStays().getRoomStay().isEmpty()) {
			if (otaHotelAvailRS.getWarnings() == null) {
				otaHotelAvailRS.setWarnings(new WarningsType());
	    			WarningType warning = new WarningType();
	    			warning.setType(CodeTables.EWT_BIZ_RULE);
	    			warning.setShortText("No availability");
	    			otaHotelAvailRS.getWarnings().getWarning().add(warning);
    			}
		}
		
		return otaHotelAvailRS;
	}

}
